package cc.mrbird.febs.common.utils;

import cc.mrbird.febs.system.domain.CostList;
import cc.mrbird.febs.system.domain.HospitalData;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 导出excel工具类
 *
 * @author 福小林
 */
public class ExcelUtils {
    /**
     * 日志框架对象
     */
    private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);

    private ExcelUtils() {

    }

    /**
     * @param titleMap excel标题map key-->标题对应的英文属性，value-->对应的中文标题名称
     * @param out      输出流对象
     * @param list     需要打印在excel上面的数据集合
     * @param <T>      泛型标识
     */
    public static <T> void exportExcel(Map<String, String> titleMap, ServletOutputStream out, List<T> list) {
        try {
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (list != null && !list.isEmpty()) {
                T t = list.get(0);
                if (t instanceof HospitalData) {
                    HospitalData hospitalData = (HospitalData) t;
                    List<Map<String, Object>> resultList = hospitalData.getResultList();
                    List<CostList> costList = (List<CostList>) resultList.get(0).get("costList");
                    int index = 1;
                    for (CostList cost : costList) {
                        String name = cost.getName();
                        titleMap.put("titleName" + index, name);
                        index++;
                    }
                }
            }
            HSSFSheet hssfSheet = getRows(titleMap, workbook);
            setExcelData(titleMap, list, hssfSheet);
            closeServletOutputStream(out, workbook);
        } catch (Exception e) {
            logger.error("导出excel信息失败！" + e.getMessage(), e);
        }
    }

    /**
     * 关闭excel导出的各种流
     *
     * @param out      输出流对象
     * @param workbook HSSFWorkbook对象
     * @throws IOException 可能抛出的IO异常
     */
    private static void closeServletOutputStream(ServletOutputStream out, HSSFWorkbook workbook) throws IOException {
        workbook.write(out);
        out.flush();
        out.close();
    }

    /**
     * 把数据放入excel表格中
     *
     * @param titleNames excel标题map key-->标题对应的英文属性，value-->对应的中文标题名称
     * @param list       需要打印在excel上面的数据集合
     * @param hssfSheet  HSSFSheet对象
     * @param <T>        泛型标识
     * @throws Exception 异常
     */
    private static <T> void setExcelData(Map<String, String> titleNames, List<T> list, HSSFSheet hssfSheet) throws Exception {
        HSSFCellStyle style = hssfSheet.getWorkbook().createCellStyle();
        // 左右居中
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        HSSFRow row;
        //如果是个人就是1 如果是小组组长 则是小组成员的个数
        int memberNumber = 0;
        //操作excel的第几行数据
        int rowNumber = 1;
        //合并的行数  即 小组成员个数乘以科室类型个数
        int mergedRowsNumber = 0;
        int dataIndex = 0;
        //小组名称和科室名称合并的起始行下标
        int firstRow = 1;
        int doctorNameFristRow = 1;
        //循环数据，打印到excel
        for (int i = 0; i < list.size(); i++) {
            dataIndex++;
            T t = list.get(i);
            int k = 4;
            HospitalData data = (HospitalData) t;
            //如果是个人就是1 如果是小组组长 则是小组成员的个数
            memberNumber = Integer.valueOf(data.getMemberNumber());
            //小组名称
            String groupName = data.getGroupName();
            //小组医生姓名
            String groupMemberName = data.getGroupMemberName();
            //小组科室名称
            String deptName = data.getDeptName();
            //费用类型分类数据
            List<Map<String, Object>> tempResult = data.getResultList();
            int size = tempResult.size();

            mergedRowsNumber = size * memberNumber;
            for (int j = 0; j < size; j++) {
                //第几行
                row = hssfSheet.createRow(rowNumber);
                rowNumber++;
                List<CostList> costList = (List<CostList>) tempResult.get(j).get("costList");
                //门诊 住院 门特 合计等科室分类
                String typename = (String) tempResult.get(j).get("typename");
                row.createCell(0).setCellValue(groupName);
                row.createCell(1).setCellValue(groupMemberName);
                row.createCell(2).setCellValue(deptName);
                row.createCell(3).setCellValue(typename);
                for (CostList cost : costList) {
                    row.createCell(k).setCellValue(cost.getValue());
                    k++;
                }
                k = 4;
            }
            //医生名称合并
            CellRangeAddress region3 = new CellRangeAddress(doctorNameFristRow, doctorNameFristRow + size - 1, 1, 1);
            hssfSheet.addMergedRegion(region3);
            //设置医生名称单元格居中
            HSSFCell cell1 = hssfSheet.getRow(doctorNameFristRow).getCell((short) 1);
            cell1.setCellStyle(style);

            doctorNameFristRow = doctorNameFristRow + size;
            // 合并单元格(4个参数，分别为起始行，结束行，起始列，结束列)
            // 行和列都是从0开始计数，且起始结束都会合并
            if (dataIndex == memberNumber) {
                //小组名称合并
                CellRangeAddress region = new CellRangeAddress(firstRow, mergedRowsNumber + firstRow - 1, 0, 0);
                hssfSheet.addMergedRegion(region);
                //设置小组名称单元格居中
                cell1 = hssfSheet.getRow(firstRow).getCell((short) 0);
                cell1.setCellStyle(style);

                //科室名称合并
                CellRangeAddress region1 = new CellRangeAddress(firstRow, mergedRowsNumber + firstRow - 1, 2, 2);
                hssfSheet.addMergedRegion(region1);
                //设置科室名称居中
                cell1 = hssfSheet.getRow(firstRow).getCell((short) 2);
                cell1.setCellStyle(style);
                firstRow = mergedRowsNumber + firstRow;
                dataIndex = 0;
            }
        }
    }


    /**
     * 获取对象的字符串
     *
     * @param obj Object对象
     * @return String
     */
    private static String getObjStr(Object obj) {
        if (StringUtils.isEmpty(obj)) {
            return "";
        } else {
            return obj.toString();
        }
    }


    /**
     * @param titleMap excel标题map key-->标题对应的英文属性，value-->对应的中文标题名称
     * @param workbook HSSFWorkbook对象
     * @return HSSFSheet已经把标题和样式设置和打印完成的对象
     */
    private static HSSFSheet getRows(Map<String, String> titleMap, HSSFWorkbook workbook) {
        Collection<String> valueCollection = titleMap.values();
        final int size = valueCollection.size();
        String[] titles = new String[size];
        titleMap.values().toArray(titles);
        HSSFSheet hssfSheet = workbook.createSheet("sheet1");
        HSSFRow row = hssfSheet.createRow(0);
        HSSFCellStyle hssfCellStyle = workbook.createCellStyle();
        hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);
        HSSFCell hssfCell;
        for (int i = 0; i < titles.length; i++) {
            hssfCell = row.createCell(i);
            hssfCell.setCellValue(titles[i]);
            hssfCell.setCellStyle(hssfCellStyle);
        }
        return hssfSheet;
    }

}
